package com.luoqy.speedy.util;

import java.beans.PropertyDescriptor;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.PropertyUtilsBean;

import com.alibaba.fastjson.JSONObject;



/**
 * @author lumberer
 * @date 2020年5月20日
 * 请求参数的处理
 */
public class ReqParams {
	/**
	 * @param obj 实体类
	 * @return 将实体类转换成Map对象返回
	 */
	public static Map<String, Object> beanToMap(Object obj) { 
        Map<String, Object> params = new HashMap<String, Object>(0); 
        try { 
            PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean(); 
            PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(obj); 
            for (int i = 0; i < descriptors.length; i++) { 
                String name = descriptors[i].getName(); 
                if (!"class".equals(name)) { 
                    params.put(name, propertyUtilsBean.getNestedProperty(obj, name)); 
                } 
            } 
        } catch (Exception e) { 
            e.printStackTrace(); 
        } 
        return params; 
	}
	/**
	 * @param params name=1&id=3
	 * @return 参数String转Map
	 * @throws UnsupportedEncodingException
	 */
	public static Map<String,Object> strToMap(String params) throws UnsupportedEncodingException{
			params = URLDecoder.decode(params, "utf-8");
			Map<String,Object> result = JSONObject.parseObject(params);
			return result;
	}

	/**
	 * 利用反射将加密参数集合集合封装成bean对象
	 *
	 * @param params
	 * @param clazz
	 * @return
	 */
	public static <T> T reqToBean(HttpServletRequest req, Class<?> clazz) throws Exception {
		Map<String, Object> map=new HashMap<>();
		Enumeration<String> enu=req.getParameterNames();
		while (enu.hasMoreElements()){
			String name=enu.nextElement();
			Object value=req.getParameter(name);
			if(name.contains("time")&&null!=value){
				if("".equals(value.toString())){
					map.put(name,null);
				}else{
					SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
					Date time=sdf.parse(req.getParameter(name).toString());
					map.put(name,time);
				}
			}else if(name.contains("roadmile")&&null!=value){
				if("".equals(value.toString())){
					map.put(name,new BigDecimal(0.00));
				}else{
					map.put(name,new BigDecimal(value.toString()));
				}
				
			}else{
				
				map.put(name,value);
			}
			
		}
		Object obj = clazz.newInstance();
		if (map != null && !map.isEmpty() && map.size() > 0) {
			for (Map.Entry<String, Object> entry : map.entrySet()) {
				String propertyName = entry.getKey(); 	// 属性名
				Object value = entry.getValue();		// 属性值
				String setMethodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
				Field field = getClassField(clazz, propertyName);	//获取和map的key匹配的属性名称
				if (field == null){
					continue;
				}
				Class<?> fieldTypeClass = field.getType();
				value = convertValType(value, fieldTypeClass);
				try {
					clazz.getMethod(setMethodName, field.getType()).invoke(obj, value);
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				}
			}
		}
		return (T) obj;
	}
	/**
	 * 利用反射将加密参数集合集合封装成bean对象
	 *
	 * @param params
	 * @param clazz
	 * @return
	 */
	public static <T> T mapToBean(String params, Class<?> clazz) throws Exception {
		Map<String, Object> map=strToMap(params);
		Object obj = clazz.newInstance();
		if (map != null && !map.isEmpty() && map.size() > 0) {
			for (Map.Entry<String, Object> entry : map.entrySet()) {
				String propertyName = entry.getKey(); 	// 属性名
				Object value = entry.getValue();		// 属性值
				String setMethodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
				Field field = getClassField(clazz, propertyName);	//获取和map的key匹配的属性名称
				if (field == null){
					continue;
				}
				Class<?> fieldTypeClass = field.getType();
				value = convertValType(value, fieldTypeClass);
				try {
					clazz.getMethod(setMethodName, field.getType()).invoke(obj, value);
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				}
			}
		}
		return (T) obj;
	}
	/**
	 * 将Map转为实体类
	 * */
	public static <T> T mapToModel(Map<String, Object> map, Class<?> clazz) throws Exception {
		Object obj = clazz.newInstance();
		if (map != null && !map.isEmpty() && map.size() > 0) {
			for (Map.Entry<String, Object> entry : map.entrySet()) {
				String propertyName = entry.getKey(); 	// 属性名
				Object value = entry.getValue();		// 属性值
				String setMethodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
				Field field = getClassField(clazz, propertyName);	//获取和map的key匹配的属性名称
				if (field == null){
					continue;
				}
				Class<?> fieldTypeClass = field.getType();
				value = convertValType(value, fieldTypeClass);
				try {
					clazz.getMethod(setMethodName, field.getType()).invoke(obj, value);
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				}
			}
		}
		return (T) obj;
	}
	/**
	 * 根据给定对象类匹配对象中的特定字段
	 * @param clazz
	 * @param fieldName
	 * @return
	 */
	private static Field getClassField(Class<?> clazz, String fieldName) {
		if (Object.class.getName().equals(clazz.getName())) {
			return null;
		}
		Field[] declaredFields = clazz.getDeclaredFields();
		for (Field field : declaredFields) {
			if (field.getName().equals(fieldName)) {
				return field;
			}
		}
		Class<?> superClass = clazz.getSuperclass();	//如果该类还有父类，将父类对象中的字段也取出
		if (superClass != null) {						//递归获取
			return getClassField(superClass, fieldName);
		}
		return null;
	}

	/**
	 * 将map的value值转为实体类中字段类型匹配的方法
	 * @param value
	 * @param fieldTypeClass
	 * @return
	 */
	private static Object convertValType(Object value, Class<?> fieldTypeClass) {
		Object retVal = null;

		if (Long.class.getName().equals(fieldTypeClass.getName())
				|| long.class.getName().equals(fieldTypeClass.getName())) {
			retVal = Long.parseLong(value.toString());
		} else if (Integer.class.getName().equals(fieldTypeClass.getName())
				|| int.class.getName().equals(fieldTypeClass.getName())) {
			retVal = Integer.parseInt(value.toString());
		} else if (Float.class.getName().equals(fieldTypeClass.getName())
				|| float.class.getName().equals(fieldTypeClass.getName())) {
			retVal = Float.parseFloat(value.toString());
		} else if (Double.class.getName().equals(fieldTypeClass.getName())
				|| double.class.getName().equals(fieldTypeClass.getName())) {
			retVal = Double.parseDouble(value.toString());
		} else {
			retVal = value;
		}
		return retVal;
	}
}
